package pt.compflow.client.api;

import java.io.IOException;
import java.util.Iterator;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.restlet.data.MediaType;
import org.restlet.data.Status;
import org.restlet.representation.EmptyRepresentation;
import org.restlet.representation.Representation;
import org.restlet.representation.StringRepresentation;
import org.restlet.resource.Delete;
import org.restlet.resource.Get;
import org.restlet.resource.Post;

import pt.compflow.Context;
import pt.compflow.flowontology.model.FLOWO;
import pt.compflow.flowontology.model.FlowOntologyModel;
import pt.compflow.flowontology.model.Person;
import pt.compflow.flowontology.model.TaskInterface;
import pt.compflow.storage.TripleStoreConnection;
import pt.compflow.tools.OntModelHelper;

import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.rdf.model.StmtIterator;
import com.hp.hpl.jena.vocabulary.RDF;

public class TaskInterfaceResource extends APIBaseResource {

//	private static final Logger LOG = LoggerFactory.getLogger(PersonResource.class);
	
	@Get("json")
	public Representation get() {
		Context context = getCompFlowContext();
		TripleStoreConnection store = context.getStoreConnection();
		store.openStore();
		
		FlowOntologyModel model = store.connectModel();
		
		Person p = getPerson(model, null, true);
		if(p == null) {
			setStatus(Status.CLIENT_ERROR_UNAUTHORIZED);
			store.closeStore();
			return new EmptyRepresentation();
		}
				
		if(getRequestAttributes().containsKey("id")) {
			String uri = FLOWO.getURI() + getRequestAttributes().get("id");
			TaskInterface ti = model.getTaskInterfaceWithURI(uri);
					
			StringRepresentation sr = new StringRepresentation(getTaskInterfaceJson(model, ti).toString(), MediaType.APPLICATION_JSON);
			store.closeStore();
			return sr;
		}
		
		// list
		JSONArray result = new JSONArray();
		Iterator<TaskInterface> it = model.listTaskInterfaces();
		while(it.hasNext()) {
			TaskInterface ti = it.next();
			result.put(getTaskInterfaceJson(model, ti));
		}
		
		StringRepresentation sr = new StringRepresentation(result.toString(), MediaType.APPLICATION_JSON);
		
		store.closeStore();
		
		return sr;
	}
	
	@Post("json")
	public Representation create(String json) throws JSONException, IOException {
						
		JSONObject request = new JSONObject(json);
		
		if(!request.has(RDF.type.getURI())) {
			setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
			return new EmptyRepresentation();
		}
		
		Context context = getCompFlowContext();
		TripleStoreConnection store = context.getStoreConnection();
		store.openStore();
		
		FlowOntologyModel model = store.connectModel();
						
		Person p = getPerson(model, null, true);
		if(p == null) {
			setStatus(Status.CLIENT_ERROR_UNAUTHORIZED);
			store.closeStore();
			return new EmptyRepresentation();
		}
		
		OntModelHelper helper = context.getEngineOntModelHelper();
		Resource type = helper.getOntModel().getOntClass(request.getString(RDF.type.getURI()));
		
		if(type == null) {
			setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
			return new EmptyRepresentation();
		}
		
		TaskInterface ti = model.createTaskInterfaceWithURI(FLOWO.getURI() + context.getInstantiator().getUniqueId("ti" + type.getLocalName(), model));
		@SuppressWarnings("unchecked")
		Iterator<String> keyIt = request.keys();
		while(keyIt.hasNext()) {
			String key = keyIt.next();
			JSONArray values = request.getJSONArray(key);
			
			for(int i=0;i<values.length();i++) {
				JSONObject obj = values.optJSONObject(i);
				
				if(obj != null) 
					ti.addProperty(model.getProperty(key), model.getResource(obj.getString("uri")));
				else
					ti.addProperty(model.getProperty(key), model.createTypedLiteral(values.get(i)));
			}
		}
		
		// get the task interface java class instance so that start() is invoked
		context.getTaskInterfaceManager().get(ti, type, helper.getOntModel(), context, store);		
		
		setStatus(Status.SUCCESS_OK);
		
		StringRepresentation sr = new StringRepresentation(ti.getLocalName(), MediaType.TEXT_PLAIN);
		
		store.closeStore();
		
		return sr;
	}
	
	//FIXME this should be a soft delete instead of a physical delete!
	@Delete("json")
	public Representation delete(String json) throws JSONException, IOException {
		
		if(!getRequestAttributes().containsKey("id")) {
			setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
			return new EmptyRepresentation();
		}
		
		Context context = getCompFlowContext();
		TripleStoreConnection store = context.getStoreConnection();
		store.openStore();
		
		FlowOntologyModel model = store.connectModel();
						
		Person p = getPerson(model, null, true);
		if(p == null) {
			setStatus(Status.CLIENT_ERROR_UNAUTHORIZED);
			store.closeStore();
			return new EmptyRepresentation();
		}
		
		TaskInterface ti = model.getTaskInterfaceWithURI(FLOWO.getURI() + getRequestAttributes().get("id"));
		if(ti == null) {
			setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
			return new EmptyRepresentation();
		}
		
		model.remove(ti, null, null);		
		
		store.closeStore();
		
		setStatus(Status.SUCCESS_NO_CONTENT);
		return new EmptyRepresentation();
	}
		
	protected JSONObject getTaskInterfaceJson(FlowOntologyModel model, TaskInterface ti) {
		JSONObject obj = new JSONObject();
		
		obj.put("uri", ti.getURI());
		obj.put("shortUri", ti.getLocalName());
		
		StmtIterator it = ti.listProperties();
		while(it.hasNext()) {
			Statement stmt = it.next();
			Property p = stmt.getPredicate();
			
			if(!obj.has(p.getURI())) {
				obj.put(p.getURI(), new JSONArray());
			}
			
			obj.getJSONArray(p.getURI()).put(stmt.getObject().toString());
		}
							
		return obj;
	}

	
}
